home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / source.exe / POSIX / MAKE / TARG.C < prev    next >
C/C++ Source or Header  |  1992-09-21  |  17KB  |  586 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
  3.  * Copyright (c) 1988, 1989 by Adam de Boor
  4.  * Copyright (c) 1989 by Berkeley Softworks
  5.  * All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Adam de Boor.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  */
  38.  
  39. #ifndef lint
  40. static char sccsid[] = "@(#)targ.c    5.9 (Berkeley) 3/1/91";
  41. #endif /* not lint */
  42.  
  43. /*-
  44.  * targ.c --
  45.  *    Functions for maintaining the Lst allTargets. Target nodes are
  46.  * kept in two structures: a Lst, maintained by the list library, and a
  47.  * hash table, maintained by the hash library.
  48.  *
  49.  * Interface:
  50.  *    Targ_Init             Initialization procedure.
  51.  *
  52.  *    Targ_NewGN            Create a new GNode for the passed target
  53.  *                          (string). The node is *not* placed in the
  54.  *                          hash table, though all its fields are
  55.  *                          initialized.
  56.  *
  57.  *    Targ_FindNode            Find the node for a given target, creating
  58.  *                          and storing it if it doesn't exist and the
  59.  *                          flags are right (TARG_CREATE)
  60.  *
  61.  *    Targ_FindList            Given a list of names, find nodes for all
  62.  *                          of them. If a name doesn't exist and the
  63.  *                          TARG_NOCREATE flag was given, an error message
  64.  *                          is printed. Else, if a name doesn't exist,
  65.  *                          its node is created.
  66.  *
  67.  *    Targ_Ignore            Return TRUE if errors should be ignored when
  68.  *                          creating the given target.
  69.  *
  70.  *    Targ_Silent            Return TRUE if we should be silent when
  71.  *                          creating the given target.
  72.  *
  73.  *    Targ_Precious            Return TRUE if the target is precious and
  74.  *                          should not be removed if we are interrupted.
  75.  *
  76.  * Debugging:
  77.  *    Targ_PrintGraph            Print out the entire graphm all variables
  78.  *                          and statistics for the directory cache. Should
  79.  *                          print something for suffixes, too, but...
  80.  */
  81.  
  82. #include      <stdio.h>
  83. #include      <time.h>
  84. #include      "make.h"
  85. #include      "hash.h"
  86.  
  87. static Lst        allTargets;    /* the list of all targets found so far */
  88. static Hash_Table targets;    /* a hash table of same */
  89.  
  90. #define HTSIZE    191        /* initial size of hash table */
  91.  
  92. /*-
  93.  *-----------------------------------------------------------------------
  94.  * Targ_Init --
  95.  *    Initialize this module
  96.  *
  97.  * Results:
  98.  *    None
  99.  *
  100.  * Side Effects:
  101.  *    The allTargets list and the targets hash table are initialized
  102.  *-----------------------------------------------------------------------
  103.  */
  104. void
  105. Targ_Init ()
  106. {
  107.     allTargets = Lst_Init (FALSE);
  108.     Hash_InitTable (&targets, HTSIZE);
  109. }
  110.  
  111. /*-
  112.  *-----------------------------------------------------------------------
  113.  * Targ_NewGN  --
  114.  *    Create and initialize a new graph node
  115.  *
  116.  * Results:
  117.  *    An initialized graph node with the name field filled with a copy
  118.  *    of the passed name
  119.  *
  120.  * Side Effects:
  121.  *    None.
  122.  *-----------------------------------------------------------------------
  123.  */
  124. GNode *
  125. Targ_NewGN (name)
  126.     char           *name;    /* the name to stick in the new node */
  127. {
  128.     register GNode *gn;
  129.  
  130.     gn = (GNode *) emalloc (sizeof (GNode));
  131.     gn->name = strdup (name);
  132.     gn->path = (char *) 0;
  133.     if (name[0] == '-' && name[1] == 'l') {
  134.     gn->type = OP_LIB;
  135.     } else {
  136.     gn->type = 0;
  137.     }
  138.     gn->unmade =        0;
  139.     gn->make =             FALSE;
  140.     gn->made =             UNMADE;
  141.     gn->childMade =     FALSE;
  142.     gn->mtime = gn->cmtime = 0;
  143.     gn->iParents =      Lst_Init (FALSE);
  144.     gn->cohorts =       Lst_Init (FALSE);
  145.     gn->parents =       Lst_Init (FALSE);
  146.     gn->children =      Lst_Init (FALSE);
  147.     gn->successors =     Lst_Init(FALSE);
  148.     gn->preds =         Lst_Init(FALSE);
  149.     gn->context =       Lst_Init (FALSE);
  150.     gn->commands =      Lst_Init (FALSE);
  151.  
  152.     return (gn);
  153. }
  154.  
  155. /*-
  156.  *-----------------------------------------------------------------------
  157.  * Targ_FindNode  --
  158.  *    Find a node in the list using the given name for matching
  159.  *
  160.  * Results:
  161.  *    The node in the list if it was. If it wasn't, return NILGNODE of
  162.  *    flags was TARG_NOCREATE or the newly created and initialized node
  163.  *    if it was TARG_CREATE
  164.  *
  165.  * Side Effects:
  166.  *    Sometimes a node is created and added to the list
  167.  *-----------------------------------------------------------------------
  168.  */
  169. GNode *
  170. Targ_FindNode (name, flags)
  171.     char           *name;    /* the name to find */
  172.     int             flags;    /* flags governing events when target not
  173.                  * found */
  174. {
  175.     GNode         *gn;          /* node in that element */
  176.     Hash_Entry      *he;          /* New or used hash entry for node */
  177.     Boolean      isNew;      /* Set TRUE if Hash_CreateEntry had to create */
  178.                   /* an entry for the node */
  179.  
  180.  
  181.     if (flags & TARG_CREATE) {
  182.     he = Hash_CreateEntry (&targets, name, &isNew);
  183.     if (isNew) {
  184.         gn = Targ_NewGN (name);
  185.         Hash_SetValue (he, gn);
  186.         (void) Lst_AtEnd (allTargets, (ClientData)gn);
  187.     }
  188.     } else {
  189.     he = Hash_FindEntry (&targets, name);
  190.     }
  191.  
  192.     if (he == (Hash_Entry *) NULL) {
  193.     return (NILGNODE);
  194.     } else {
  195.     return ((GNode *) Hash_GetValue (he));
  196.     }
  197. }
  198.  
  199. /*-
  200.  *-----------------------------------------------------------------------
  201.  * Targ_FindList --
  202.  *    Make a complete list of GNodes from the given list of names 
  203.  *
  204.  * Results:
  205.  *    A complete list of graph nodes corresponding to all instances of all
  206.  *    the names in names. 
  207.  *
  208.  * Side Effects:
  209.  *    If flags is TARG_CREATE, nodes will be created for all names in
  210.  *    names which do not yet have graph nodes. If flags is TARG_NOCREATE,
  211.  *    an error message will be printed for each name which can't be found.
  212.  * -----------------------------------------------------------------------
  213.  */
  214. Lst
  215. Targ_FindList (names, flags)
  216.     Lst               names;    /* list of names to find */
  217.     int            flags;    /* flags used if no node is found for a given
  218.                  * name */
  219. {
  220.     Lst            nodes;    /* result list */
  221.     register LstNode  ln;        /* name list element */
  222.     register GNode *gn;        /* node in tLn */
  223.     char          *name;
  224.  
  225.     nodes = Lst_Init (FALSE);
  226.  
  227.     if (Lst_Open (names) == FAILURE) {
  228.     return (nodes);
  229.     }
  230.     while ((ln = Lst_Next (names)) != NILLNODE) {
  231.     name = (char *)Lst_Datum(ln);
  232.     gn = Targ_FindNode (name, flags);
  233.     if (gn != NILGNODE) {
  234.         /*
  235.          * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
  236.          * are added to the list in the order in which they were
  237.          * encountered in the makefile.
  238.          */
  239.         (void) Lst_AtEnd (nodes, (ClientData)gn);
  240.         if (gn->type & OP_DOUBLEDEP) {
  241.         (void)Lst_Concat (nodes, gn->cohorts, LST_CONCNEW);
  242.         }
  243.     } else if (flags == TARG_NOCREATE) {
  244.         Error ("\"%s\" -- target unknown.", name);
  245.     }
  246.     }
  247.     Lst_Close (names);
  248.     return (nodes);
  249. }
  250.  
  251. /*-
  252.  *-----------------------------------------------------------------------
  253.  * Targ_Ignore  --
  254.  *    Return true if should ignore errors when creating gn
  255.  *
  256.  * Results:
  257.  *    TRUE if should ignore errors
  258.  *
  259.  * Side Effects:
  260.  *    None
  261.  *-----------------------------------------------------------------------
  262.  */
  263. Boolean
  264. Targ_Ignore (gn)
  265.     GNode          *gn;        /* node to check for */
  266. {
  267.     if (ignoreErrors || gn->type & OP_IGNORE) {
  268.     return (TRUE);
  269.     } else {
  270.     return (FALSE);
  271.     }
  272. }
  273.  
  274. /*-
  275.  *-----------------------------------------------------------------------
  276.  * Targ_Silent  --
  277.  *    Return true if be silent when creating gn
  278.  *
  279.  * Results:
  280.  *    TRUE if should be silent
  281.  *
  282.  * Side Effects:
  283.  *    None
  284.  *-----------------------------------------------------------------------
  285.  */
  286. Boolean
  287. Targ_Silent (gn)
  288.     GNode          *gn;        /* node to check for */
  289. {
  290.     if (beSilent || gn->type & OP_SILENT) {
  291.     return (TRUE);
  292.     } else {
  293.     return (FALSE);
  294.     }
  295. }
  296.  
  297. /*-
  298.  *-----------------------------------------------------------------------
  299.  * Targ_Precious --
  300.  *    See if the given target is precious
  301.  *
  302.  * Results:
  303.  *    TRUE if it is precious. FALSE otherwise
  304.  *
  305.  * Side Effects:
  306.  *    None
  307.  *-----------------------------------------------------------------------
  308.  */
  309. Boolean
  310. Targ_Precious (gn)
  311.     GNode          *gn;        /* the node to check */
  312. {
  313.     if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) {
  314.     return (TRUE);
  315.     } else {
  316.     return (FALSE);
  317.     }
  318. }
  319.  
  320. /******************* DEBUG INFO PRINTING ****************/
  321.  
  322. static GNode      *mainTarg;    /* the main target, as set by Targ_SetMain */
  323. /*- 
  324.  *-----------------------------------------------------------------------
  325.  * Targ_SetMain --
  326.  *    Set our idea of the main target we'll be creating. Used for
  327.  *    debugging output.
  328.  *
  329.  * Results:
  330.  *    None.
  331.  *
  332.  * Side Effects:
  333.  *    "mainTarg" is set to the main target's node.
  334.  *-----------------------------------------------------------------------
  335.  */
  336. void
  337. Targ_SetMain (gn)
  338.     GNode   *gn;      /* The main target we'll create */
  339. {
  340.     mainTarg = gn;
  341. }
  342.  
  343. static int
  344. TargPrintName (gn, ppath)
  345.     GNode          *gn;
  346.     int            ppath;
  347. {
  348.     printf ("%s ", gn->name);
  349. #ifdef notdef
  350.     if (ppath) {
  351.     if (gn->path) {
  352.         printf ("[%s]  ", gn->path);
  353.     }
  354.     if (gn == mainTarg) {
  355.         printf ("(MAIN NAME)  ");
  356.     }
  357.     }
  358. #endif notdef
  359.     return (0);
  360. }
  361.  
  362.  
  363. int
  364. Targ_PrintCmd (cmd)
  365.     char           *cmd;
  366. {
  367.     printf ("\t%s\n", cmd);
  368.     return (0);
  369. }
  370.  
  371. /*-
  372.  *-----------------------------------------------------------------------
  373.  * Targ_FmtTime --
  374.  *    Format a modification time in some reasonable way and return it.
  375.  *
  376.  * Results:
  377.  *    The time reformatted.
  378.  *
  379.  * Side Effects:
  380.  *    The time is placed in a static area, so it is overwritten
  381.  *    with each call.
  382.  *
  383.  *-----------------------------------------------------------------------
  384.  */
  385. char *
  386. Targ_FmtTime (time)
  387.     time_t    time;
  388. {
  389.     struct tm          *parts;
  390.     static char          buf[40];
  391.     static char          *months[] = {
  392.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  393.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  394.     };
  395.  
  396. //#ifdef DF_POSIX
  397. //    strcpy (buf, "localtime");
  398. //#else
  399.     parts = localtime(&time);
  400.  
  401.     sprintf (buf, "%d:%02d:%02d %s %d, 19%d",
  402.          parts->tm_hour, parts->tm_min, parts->tm_sec,
  403.          months[parts->tm_mon], parts->tm_mday, parts->tm_year);
  404. //#endif
  405.     return(buf);
  406. }
  407.     
  408. /*-
  409.  *-----------------------------------------------------------------------
  410.  * Targ_PrintType --
  411.  *    Print out a type field giving only those attributes the user can
  412.  *    set.
  413.  *
  414.  * Results:
  415.  *
  416.  * Side Effects:
  417.  *
  418.  *-----------------------------------------------------------------------
  419.  */
  420. void
  421. Targ_PrintType (type)
  422.     register int    type;
  423. {
  424.     register int    tbit;
  425.     
  426. #ifdef __STDC__
  427. #define PRINTBIT(attr)    case CONCAT(OP_,attr): printf("." #attr " "); break
  428. #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break
  429. #else
  430. #define PRINTBIT(attr)     case CONCAT(OP_,attr): printf(".attr "); break
  431. #define PRINTDBIT(attr)    case CONCAT(OP_,attr): if (DEBUG(TARG)) printf(".attr "); break
  432. #endif /* __STDC__ */
  433.  
  434.     type &= ~OP_OPMASK;
  435.  
  436.     while (type) {
  437.     tbit = 1 << (ffs(type) - 1);
  438.     type &= ~tbit;
  439.  
  440.     switch(tbit) {
  441.         PRINTBIT(OPTIONAL);
  442.         PRINTBIT(USE);
  443.         PRINTBIT(EXEC);
  444.         PRINTBIT(IGNORE);
  445.         PRINTBIT(PRECIOUS);
  446.         PRINTBIT(SILENT);
  447.         PRINTBIT(MAKE);
  448.         PRINTBIT(JOIN);
  449.         PRINTBIT(INVISIBLE);
  450.         PRINTBIT(NOTMAIN);
  451.         PRINTDBIT(LIB);
  452.         /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
  453.         case OP_MEMBER: if (DEBUG(TARG)) printf(".MEMBER "); break;
  454.         PRINTDBIT(ARCHV);
  455.     }
  456.     }
  457. }
  458.  
  459. /*-
  460.  *-----------------------------------------------------------------------
  461.  * TargPrintNode --
  462.  *    print the contents of a node
  463.  *-----------------------------------------------------------------------
  464.  */
  465. static int
  466. TargPrintNode (gn, pass)
  467.     GNode         *gn;
  468.     int              pass;
  469. {
  470.     if (!OP_NOP(gn->type)) {
  471.     printf("#\n");
  472.     if (gn == mainTarg) {
  473.         printf("# *** MAIN TARGET ***\n");
  474.     }
  475.     if (pass == 2) {
  476.         if (gn->unmade) {
  477.         printf("# %d unmade children\n", gn->unmade);
  478.         } else {
  479.         printf("# No unmade children\n");
  480.         }
  481.         if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
  482.         if (gn->mtime != 0) {
  483.             printf("# last modified %s: %s\n",
  484.                   Targ_FmtTime(gn->mtime),
  485.                   (gn->made == UNMADE ? "unmade" :
  486.                    (gn->made == MADE ? "made" :
  487.                 (gn->made == UPTODATE ? "up-to-date" :
  488.                  "error when made"))));
  489.         } else if (gn->made != UNMADE) {
  490.             printf("# non-existent (maybe): %s\n",
  491.                   (gn->made == MADE ? "made" :
  492.                    (gn->made == UPTODATE ? "up-to-date" :
  493.                 (gn->made == ERROR ? "error when made" :
  494.                  "aborted"))));
  495.         } else {
  496.             printf("# unmade\n");
  497.         }
  498.         }
  499.         if (!Lst_IsEmpty (gn->iParents)) {
  500.         printf("# implicit parents: ");
  501.         Lst_ForEach (gn->iParents, TargPrintName, (ClientData)0);
  502.         putc ('\n', stdout);
  503.         }
  504.     }
  505.     if (!Lst_IsEmpty (gn->parents)) {
  506.         printf("# parents: ");
  507.         Lst_ForEach (gn->parents, TargPrintName, (ClientData)0);
  508.         putc ('\n', stdout);
  509.     }
  510.     
  511.     printf("%-16s", gn->name);
  512.     switch (gn->type & OP_OPMASK) {
  513.         case OP_DEPENDS:
  514.         printf(": "); break;
  515.         case OP_FORCE:
  516.         printf("! "); break;
  517.         case OP_DOUBLEDEP:
  518.         printf(":: "); break;
  519.     }
  520.     Targ_PrintType (gn->type);
  521.     Lst_ForEach (gn->children, TargPrintName, (ClientData)0);
  522.     putc ('\n', stdout);
  523.     Lst_ForEach (gn->commands, Targ_PrintCmd, (ClientData)0);
  524.     printf("\n\n");
  525.     if (gn->type & OP_DOUBLEDEP) {
  526.         Lst_ForEach (gn->cohorts, TargPrintNode, (ClientData)pass);
  527.     }
  528.     }
  529.     return (0);
  530. }
  531.  
  532. /*-
  533.  *-----------------------------------------------------------------------
  534.  * TargPrintOnlySrc --
  535.  *    Print only those targets that are just a source.
  536.  *
  537.  * Results:
  538.  *    0.
  539.  *
  540.  * Side Effects:
  541.  *    The name of each file is printed preceeded by #\t
  542.  *
  543.  *-----------------------------------------------------------------------
  544.  */
  545. static int
  546. TargPrintOnlySrc(gn)
  547.     GNode         *gn;
  548. {
  549.     if (OP_NOP(gn->type)) {
  550.     printf("#\t%s [%s]\n", gn->name,
  551.           gn->path ? gn->path : gn->name);
  552.     }
  553.     return (0);
  554. }
  555.  
  556. /*-
  557.  *-----------------------------------------------------------------------
  558.  * Targ_PrintGraph --
  559.  *    print the entire graph. heh heh
  560.  *
  561.  * Results:
  562.  *    none
  563.  *
  564.  * Side Effects:
  565.  *    lots o' output
  566.  *-----------------------------------------------------------------------
  567.  */
  568. Targ_PrintGraph (pass)
  569.     int        pass;     /* Which pass this is. 1 => no processing
  570.              * 2 => processing done */
  571. {
  572.     printf("#*** Input graph:\n");
  573.     Lst_ForEach (allTargets, TargPrintNode, (ClientData)pass);
  574.     printf("\n\n");
  575.     printf("#\n#   Files that are only sources:\n");
  576.     Lst_ForEach (allTargets, TargPrintOnlySrc);
  577.     printf("#*** Global Variables:\n");
  578.     Var_Dump (VAR_GLOBAL);
  579.     printf("#*** Command-line Variables:\n");
  580.     Var_Dump (VAR_CMD);
  581.     printf("\n");
  582.     Dir_PrintDirectories();
  583.     printf("\n");
  584.     Suff_PrintAll();
  585. }
  586.